/**
 * @file    victron_can.c
 * @brief   逆变器协议-维克创-CAN通信接口V6.0
 * @author  Liuwei
 * @version 1.0.1
 * @date    2023-04-30
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2023-04-30 <td>1.0.1     <td>Liuwei   <td>首次创建
 * </table>
 */

/* includes ------------------------------------------------------------------*/
#include "victron_can.h"
#include "If_can.h"
#include "var_mng.h"
#include "param_mng.h"
#include "cfg_prj.h"
#include "diagnosis.h"
#include "parallel.h"
/* macro/define --------------------------------------------------------------*/
#define ALARM_UN_SUP   (0)   /* 不支持故障 */
#define ALARM_HAPPEN   (1)   /* 发生 */
#define ALARM_NORMAL   (2)   /* 正常 */
#define USE_EXT_FRAME  (1)   /* 是否开启扩展报文发送 */
/* typedef -------------------------------------------------------------------*/
typedef struct 
{
    uint16_t can_id;      /* !< 报文ID */
    uint16_t send_cycle; /* !< 发送周期 */
    uint16_t send_cnt;   /* !< 计时器 */
    void(*pfunc_get_frame_msg)(can_frame_type *);
}send_frame_type;

typedef union 
{
    uint32_t word_data;
    struct 
    {
        uint32_t general_alarm : 2;
        uint32_t ov_alarm : 2;
        uint32_t uv_alarm : 2;
        uint32_t otd_alarm : 2;
		
        uint32_t utd_alarm : 2;
        uint32_t otc_alarm : 2;
		uint32_t utc_alarm : 2;
		uint32_t ocd_alarm : 2;
		
		uint32_t occ_alarm : 2;
		uint32_t contactor_alarm : 2; /*!< 接触器告警 */
		uint32_t sc_alarm : 2;
		uint32_t bsm_int_alarm : 2;
		
		uint32_t cell_blc_alarm : 2;
		uint32_t reserved : 6;
	}name;
}alarm_msg_type;

typedef struct
{
	uint32_t word_data;
    struct 
    {
		uint32_t general_warn : 2;
        uint32_t ov_warn : 2;
        uint32_t uv_warn : 2;
        uint32_t otd_warn : 2;
		
        uint32_t utd_warn : 2;
        uint32_t otc_warn : 2;
		uint32_t utc_warn : 2;
		uint32_t ocd_warn : 2;
		
		uint32_t occ_warn : 2;
		uint32_t contactor_warn : 2; /*!< 接触器告警 */
		uint32_t sc_warn : 2;
		uint32_t bsm_int_warn : 2;
		
		uint32_t cell_blc_warn : 2;
		uint32_t system_status : 2;
		uint32_t reserved2 : 4;
    }name;
}warn_msg_type;

/* local functions -----------------------------------------------------------*/
static void can_get_0x351_msg(can_frame_type *can_msg);
static void can_get_0x355_msg(can_frame_type *can_msg);
static void can_get_0x356_msg(can_frame_type *can_msg);
static void can_get_0x35A_msg(can_frame_type *can_msg);
static void can_get_0x35E_msg(can_frame_type *can_msg);
static void can_get_0x35F_msg(can_frame_type *can_msg);

#if USE_EXT_FRAME
	static void can_get_0x370_msg(can_frame_type *can_msg);
	static void can_get_0x371_msg(can_frame_type *can_msg);
	static void can_get_0x372_msg(can_frame_type *can_msg);
	static void can_get_0x373_msg(can_frame_type *can_msg);
	static void can_get_0x374_msg(can_frame_type *can_msg);
	static void can_get_0x375_msg(can_frame_type *can_msg);
	static void can_get_0x376_msg(can_frame_type *can_msg);
	static void can_get_0x377_msg(can_frame_type *can_msg);
	static void can_get_0x378_msg(can_frame_type *can_msg);
	static void can_get_0x379_msg(can_frame_type *can_msg);
	static void can_get_0x380_msg(can_frame_type *can_msg);
	static void can_get_0x381_msg(can_frame_type *can_msg);
	static void can_get_0x382_msg(can_frame_type *can_msg);
#endif
/* static variables ----------------------------------------------------------*/
static send_frame_type send_frame_list[] = 
{
    {0x351 , 1000 , 0 ,can_get_0x351_msg },
    {0x355 , 1000 , 0 ,can_get_0x355_msg },
    {0x356 , 1000 , 0 ,can_get_0x356_msg },
    {0x35A , 1000 , 0 ,can_get_0x35A_msg },
    {0x35E , 1000 , 0 ,can_get_0x35E_msg },
    {0x35F , 1000 , 0 ,can_get_0x35F_msg },
	
//	/* 扩展预留 */
#if USE_EXT_FRAME
	{0x370 , 1000 , 0 ,can_get_0x370_msg },
    {0x371 , 1000 , 0 ,can_get_0x371_msg },
    {0x372 , 1000 , 0 ,can_get_0x372_msg },
    {0x373 , 1000 , 0 ,can_get_0x373_msg },
    {0x374 , 1000 , 0 ,can_get_0x374_msg },
    {0x375 , 1000 , 0 ,can_get_0x375_msg },
    {0x376 , 1000 , 0 ,can_get_0x376_msg },
	{0x377 , 1000 , 0 ,can_get_0x377_msg },
    {0x378 , 1000 , 0 ,can_get_0x378_msg },
    {0x379 , 1000 , 0 ,can_get_0x379_msg },
    {0x380 , 1000 , 0 ,can_get_0x380_msg },
    {0x381 , 1000 , 0 ,can_get_0x381_msg },
    {0x382 , 1000 , 0 ,can_get_0x382_msg },
#endif
};

#define CAN_LIST_NUM     (sizeof(send_frame_list)/sizeof(send_frame_type))
/* global variables ----------------------------------------------------------*/

/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
/**
 * @brief  获取需要发送的数据信息
 * @param  cycle
 * @param  can_buf
 * @return uint8_t 
 */
uint8_t victron_can_get_msg(uint32_t cycle , can_frame_type *can_buf)
{
    uint8_t i = 0;
    uint8_t msg_num = 0;

    for( i = 0; i < CAN_LIST_NUM; ++ i)
    {
        send_frame_list[i].send_cnt += cycle;
        if(send_frame_list[i].send_cnt >= send_frame_list[i].send_cycle)
        {
            send_frame_list[i].send_cnt = 0;
            send_frame_list[i].pfunc_get_frame_msg(&can_buf[msg_num ++]); 
        }
    }

    return msg_num;
}

/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */
static void can_get_0x351_msg(can_frame_type *can_msg)
{
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x351;

    can_msg->data.half_buf[0] = var_get_data(VAR_ID_TP_SOP_CV);
    can_msg->data.half_buf[1] = var_get_data(VAR_ID_TP_SOP_CC);
    can_msg->data.half_buf[2] = var_get_data(VAR_ID_TP_SOP_DC);
    can_msg->data.half_buf[3] = var_get_data(VAR_ID_TP_SOP_DV);
}

static void can_get_0x355_msg(can_frame_type *can_msg)
{
	uint8_t soh = 0;
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x355;

    can_msg->data.half_buf[0] = var_get_data(VAR_ID_TP_SOC);
	soh = var_get_data(VAR_ID_TP_SOH);
	if(soh > 100)
		soh = 100;
    can_msg->data.half_buf[1] = soh;
    can_msg->data.half_buf[2] = var_get_data(VAR_ID_TP_SOC)*100; // 协议要求高分辨率SOC
    can_msg->data.half_buf[3] = 0;
}

static void can_get_0x356_msg(can_frame_type *can_msg)
{
    int32_t temp = 0;
    int16_t curr = 0;
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x356;

    can_msg->data.half_buf[0] = var_get_data(VAR_ID_BATT_VOLT);
    temp = (var_get_data(VAR_ID_TP_CURR_H) << 16) + var_get_data(VAR_ID_TP_CURR_L);
    curr = temp * 0.1;
    can_msg->data.half_buf[1] = curr;
    can_msg->data.half_buf[2] = var_get_data(VAR_ID_TP_AVG_TEMP) - 2731;
    can_msg->data.half_buf[3] = var_get_data(VAR_ID_TP_CYCLE);
}

extern master_data_type master_data_reg;
static void can_get_0x35A_msg(can_frame_type *can_msg)
{
	/* 告警及保护信息 */
	alarm_msg_type alarm_msg = {0};
	warn_msg_type warn_msg = {0};
	
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x35A;

	alarm_msg.name.occ_alarm = master_data_reg.total_prp_msg.bit.occ | master_data_reg.total_prp_msg.bit.occ2;
	alarm_msg.name.ocd_alarm = master_data_reg.total_prp_msg.bit.ocd | master_data_reg.total_prp_msg.bit.ocd2;
	alarm_msg.name.otc_alarm = master_data_reg.total_prp_msg.bit.otc;
	alarm_msg.name.utc_alarm = master_data_reg.total_prp_msg.bit.utc;
	alarm_msg.name.sc_alarm = master_data_reg.total_prp_msg.bit.sc;
	alarm_msg.name.otd_alarm = master_data_reg.total_prp_msg.bit.otd;
	alarm_msg.name.utd_alarm = master_data_reg.total_prp_msg.bit.utd;

    can_msg->data.word_buf[0] = alarm_msg.word_data;
    can_msg->data.word_buf[1] = warn_msg.word_data;
}

static void can_get_0x35E_msg(can_frame_type *can_msg)
{
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x35E;

    param_get_multi_data(PAR_ID_MFT_CODE , 4 , can_msg->data.half_buf);
}

static void can_get_0x35F_msg(can_frame_type *can_msg)
{
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x35F;

    can_msg->data.byte_buf[0] = 'J';
	can_msg->data.byte_buf[1] = 'B';
    can_msg->data.byte_buf[2] = SOFT_VER_MAIN;
	can_msg->data.byte_buf[3] = SOFT_VER_RELEASE;
    can_msg->data.half_buf[2] = 0;
    can_msg->data.half_buf[3] = 0;
}

#if USE_EXT_FRAME
void can_get_0x370_msg(can_frame_type *can_msg)
{
	can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x370;
    
	param_get_multi_data(PAR_ID_BMS_CODE ,4 , can_msg->data.half_buf);
}

static void can_get_0x371_msg(can_frame_type *can_msg)
{
	/* BMS名称 */
	can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x371;
    
    param_get_multi_data(PAR_ID_BMS_CODE + 4, 4 , can_msg->data.half_buf);
}

static void can_get_0x372_msg(can_frame_type *can_msg)
{
	can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x372;
    
    can_msg->data.half_buf[0] = master_data_reg.parallel_num;
    can_msg->data.half_buf[1] = 0;
    can_msg->data.half_buf[2] = 0;
    can_msg->data.half_buf[3] = 0;
}

static void can_get_0x373_msg(can_frame_type *can_msg)
{
	/* BMS名称 */
	can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x373;
	
    can_msg->data.half_buf[0] = var_get_data(VAR_ID_TP_MINC_VOLT);
    can_msg->data.half_buf[1] = var_get_data(VAR_ID_TP_MAXC_VOLT); 
	can_msg->data.half_buf[2] = var_get_data(VAR_ID_TP_MINT_VAL) * 0.1;
    can_msg->data.half_buf[3] = var_get_data(VAR_ID_TP_MAXT_VAL) * 0.1;
}

static void can_get_0x374_msg(can_frame_type *can_msg)
{
	can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x374;
    
	can_msg->data.byte_buf[0] = 'I';
    can_msg->data.byte_buf[1] = 'D';
    can_msg->data.byte_buf[2] = ':';
    can_msg->data.byte_buf[3] = (((master_data_reg.min_volt_sn >> 8) >> 4) & 0x0f) + 0x30;
    can_msg->data.byte_buf[4] = ((master_data_reg.min_volt_sn >> 8) & 0xf) + 0x30;
	can_msg->data.byte_buf[5] = '.';
	can_msg->data.byte_buf[6] = ((master_data_reg.min_volt_sn >> 4) & 0x0f) + 0x30;
	can_msg->data.byte_buf[7] = (master_data_reg.min_volt_sn & 0x0f) + 0x30;
}

static void can_get_0x375_msg(can_frame_type *can_msg)
{
	can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x375;
    
	can_msg->data.byte_buf[0] = 'I';
    can_msg->data.byte_buf[1] = 'D';
    can_msg->data.byte_buf[2] = ':';
    can_msg->data.byte_buf[3] = (((master_data_reg.max_volt_sn >> 8) >> 4) & 0x0f) + 0x30;
    can_msg->data.byte_buf[4] = ((master_data_reg.max_volt_sn >> 8) & 0xf) + 0x30;
	can_msg->data.byte_buf[5] = '.';
	can_msg->data.byte_buf[6] = ((master_data_reg.max_volt_sn >> 4) & 0x0f) + 0x30;
	can_msg->data.byte_buf[7] = (master_data_reg.max_volt_sn & 0x0f) + 0x30;
}

static void can_get_0x376_msg(can_frame_type *can_msg)
{
	can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x376;
    
    can_msg->data.byte_buf[0] = 'I';
    can_msg->data.byte_buf[1] = 'D';
    can_msg->data.byte_buf[2] = ':';
    can_msg->data.byte_buf[3] = 0x30;
    can_msg->data.byte_buf[4] = 0x31;
	can_msg->data.byte_buf[5] = '.';
	can_msg->data.byte_buf[6] = ((var_get_data(VAR_ID_MIN_TEMP_SN) >> 4) & 0x0f) + 0x30;
	can_msg->data.byte_buf[7] = (var_get_data(VAR_ID_MIN_TEMP_SN) & 0x0f) + 0x30;
}

static void can_get_0x377_msg(can_frame_type *can_msg)
{
	can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x377;
    
    can_msg->data.byte_buf[0] = 'I';
    can_msg->data.byte_buf[1] = 'D';
    can_msg->data.byte_buf[2] = ':';
    can_msg->data.byte_buf[3] = 0x30;
    can_msg->data.byte_buf[4] = 0x31;
	can_msg->data.byte_buf[5] = '.';
	can_msg->data.byte_buf[6] = ((var_get_data(VAR_ID_MAX_TEMP_SN) >> 4) & 0x0f) + 0x30;
	can_msg->data.byte_buf[7] = (var_get_data(VAR_ID_MAX_TEMP_SN) & 0x0f) + 0x30;
}

static void can_get_0x378_msg(can_frame_type *can_msg)
{
	/* 输入输出功率 */
	can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x378;
    
	can_msg->data.word_buf[0] = 0;
	can_msg->data.word_buf[1] = 0;
//	if(master_data_reg.total_bus_curr > 0)
//		can_msg->data.word_buf[0] = master_data_reg.total_bus_curr * ;  /*!< 输入能量 */
//	else
//		can_msg->data.word_buf[0] = 0; 
//    can_msg->data.word_buf[1] = 0;  /*!< 输出能量 */
}

static void can_get_0x379_msg(can_frame_type *can_msg)
{	
	/* 输入输出功率 */
	can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x379;
    
    can_msg->data.half_buf[0] = master_data_reg.parallel_num * param_get_data(PAR_ID_STD_CAP) * 0.01;  /*!< 系统总额定安时数 */
    can_msg->data.half_buf[1] = 0;
    can_msg->data.half_buf[2] = 0;
    can_msg->data.half_buf[3] = 0;
}
static void can_get_0x380_msg(can_frame_type *can_msg)
{
	/* sn码 */
	can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x380;
    
	param_get_multi_data(PAR_ID_SN_CODE , 4 , can_msg->data.half_buf);
}	

static void can_get_0x381_msg(can_frame_type *can_msg)
{
	/* sn码 */
	can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x381;
    
	param_get_multi_data(PAR_ID_SN_CODE + 4 , 4 , can_msg->data.half_buf);
}

static void can_get_0x382_msg(can_frame_type *can_msg)
{
	can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x382;
	
	can_msg->data.byte_buf[0] = 'J';
    can_msg->data.byte_buf[1] = 'B';
    can_msg->data.byte_buf[2] = 'D';
    can_msg->data.byte_buf[3] = 0;
    can_msg->data.byte_buf[4] = 0;
	can_msg->data.byte_buf[5] = 0;
	can_msg->data.byte_buf[6] = 0;
	can_msg->data.byte_buf[7] = 0;
}
#endif
/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/


